<template>
  <div class="home-middle-inside" ref="middleViewRef">
    <div class="middle-area">
      <div class="left">
        <div class="item" @click="handleBack" v-if="shownTopOperate">
          <i class="el-icon-back"/>
          <span>返回</span>
        </div>
      </div>
      <div class="middle">{{ templateInfo.title || '标题' }}</div>
      <div class="right">
        <template v-if="shownTopOperate">
          <div class="item" @click="clearFormWidget">
            <i class="el-icon-delete"/>
            <span>清空</span>
          </div>
          <div class="item" @click="handlePreview" v-if="false">预览</div>
          <div class="item" @click="handleExport">
            <i class="el-icon-camera"/>
            <span>预览JSON</span>
          </div>
          <!-- 上真实终端预览效果 -->
          <div class="item" @click="handleUpScreenPreview" v-if="this.isProd">
            <i class="el-icon-camera"/>
            <span>上屏预览</span>
          </div>

          <div class="item" @click="handlePublic">
            <i class="el-icon-files"/>
            <span>发布</span>
          </div>
        </template>

      </div>
    </div>

    <div class="preView vhView" ref="preViewRef" v-if="true">

      <div class="cvsWin" id="screen-info" ref="cvsRef">
        <div class="form-widget-container">
          <el-form
              :size="size"
              :validate-on-rule-change="false"
              :label-position="labelPosition"
              class="full-height-width widget-form"
              :class="[customClass, `${layoutType}-layout`]"
          >
            <draggable
                :list="designer.widgetList"
                class="draggable-area"
                handle=".drag-handler"
                @end="onDragEnd"
                @add="onDragAdd"
                @update="onDragUpdate"
                :move="checkMove"
                v-bind="{group:'dragGroup', ghostClass: 'ghost',animation: 300}"
            >
              <transition-group name="fade" tag="div" class="form-widget-list" :style="getStyle('formListInfo')">
                <template v-for="(widget, index) in designer.widgetList">
                  <template v-if="'container' === widget.category">
                    <component
                        :is="getWidgetName(widget)"
                        :widget="widget"
                        :designer="designer"
                        :key="widget.id"
                        :parent-list="designer.widgetList"
                        :selected-widget="designer.selectedWidget"
                        :index-of-parent-list="index"
                        :parent-widget="null"/>
                  </template>
                  <template v-else>
                    <component
                        v-if="true"
                        :is="getWidgetName(widget)"
                        :field="widget"
                        :designer="designer"
                        :key="widget.id"
                        :widgetKey="widget.id"
                        :parent-list="designer.widgetList"
                        :selected-widget="designer.selectedWidget"
                        :index-of-parent-list="index"
                        :parent-widget="null"
                        :design-state="true"
                    />
                  </template>
                </template>
              </transition-group>
            </draggable>
          </el-form>
        </div>
      </div>

    </div>

    <!--导出弹层-->
    <CodeEditor
        :mode="exportInfo.mode"
        :visible="exportInfo.visible"
        :readonly="exportInfo.readonly"
        :info="exportInfo.jsonContent"
        @handleCancel="handleCancel"
    />

    <!--模板预览-->
    <TemplatePreview
        :info="previewInfo.id"
        :visible="previewInfo.visible"
        :htmlPath="previewInfo.htmlPath"
        @handleCancel="handleCancel"
        :resolution="previewInfo.resolution"
    />
  </div>
</template>

<script>
import lodash from "lodash"
import {v4 as uuid} from 'uuid';
import {NoticeBar} from 'vant';
import {pxToVw} from "@/utils/common";
import Draggable from "vuedraggable";
import Components from "./components";
import {deepClone} from "@/utils/designer/util"
import {ModelDesignApi} from "@/api/modeldesign";
import CodeEditor from '@/components/public/layer/code-editor'
import TemplatePreview from '@/components/public/layer/template/preview'
import {ApiUtils} from "@/utils/apiUtils";

export default {
  name: "HomeMiddle",

  components: {
    Draggable,
    NoticeBar,
    CodeEditor,
    ...Components,
    TemplatePreview,
  },

  props: {
    designer: Object,
    formConfig: Object,
    optionData: {
      type: Object,
      default: () => ({})
    },
    globalDsv: {
      type: Object,
      default: () => ({})
    },
  },

  provide() {
    return {
      refList: this.widgetRefList,
      formConfig: this.formConfig,
      getGlobalDsv: () => this.globalDsv, // 全局数据源变量
      globalOptionData: this.optionData,
      getOptionData: () => this.optionData,
      globalModel: {
        formModel: this.formModel,
      }
    };
  },

  inject: ["getDesignerConfig"],

  data() {
    return {
      uuid: '',
      tipsShow: true,
      formModel: {},
      widgetRefList: {},
      deviceSize: '1920*1080',
      previewInfo: {
        id: '',
        htmlPath: '',
        visible: false,
        resolution: (this.deviceSize) || '1920*1080',
      },
      exportInfo: {
        mode: 'json',
        visible: false,
        readonly: true,
        jsonContent: JSON.stringify(Object()),
        jsonRawContent: JSON.stringify(Object()),
      },
      isProd: false

    };
  },

  computed: {
    getStyle() {
      return function (val) {
        const self = this;
        let {parentInfo} = (self.formConfig) || Array();
        let Obj = Object();
        if (parentInfo) {
          switch (val) {
            case 'formListInfo':
              if (!!(parentInfo.backgroundColor)) {
                Reflect.set(Obj, 'backgroundColor', (parentInfo.backgroundColor));
              }
              if (!!(parentInfo.backgroundImage)) {
                Reflect.set(Obj, 'backgroundImage', `url(${parentInfo.backgroundImage})`);
              }
              if (!!(parentInfo.paddingTop)) {
                Reflect.set(Obj, 'paddingTop', pxToVw(parentInfo.paddingTop));
              }
              if (!!(parentInfo.paddingBottom)) {
                Reflect.set(Obj, 'paddingBottom', pxToVw(parentInfo.paddingBottom));
              }
              if (!!(parentInfo.paddingLeft)) {
                Reflect.set(Obj, 'paddingLeft', pxToVw(parentInfo.paddingLeft));
              }
              if (!!(parentInfo.paddingRight)) {
                Reflect.set(Obj, 'paddingRight', pxToVw(parentInfo.paddingRight));
              }
              return Obj;
          }
        }
      }
    },

    labelPosition() {
      if (!!this.designer.formConfig && !!this.designer.formConfig.labelPosition) {
        return this.designer.formConfig.labelPosition;
      }
      return "left";
    },

    size() {
      if (!!this.designer.formConfig && !!this.designer.formConfig.size) {
        return this.designer.formConfig.size;
      }
      return "medium";
    },

    customClass() {
      return this.designer.formConfig.customClass || "";
    },

    layoutType() {
      return this.designer.getLayoutType();
    },

    // 右侧选择是否显示
    shownTopOperate() {
      let {type} = (this.$route.params);
      switch (type) {
        case 'create':
        case 'detail':
          return true;
        case 'edit':
          return false
      }
    },

    // 获取designer数据
    getDesigner() {
      let {type} = (this.$route.params);
      switch (type) {
        case 'create':
        case 'detail':
          return (this.designer);
        case 'edit':
          return (this.designer)
      }
    },

    // 请求后端获取的数据
    templateInfo() {
      return this.$store.getters['templateDetails/getTemplateInfo']
    }

  },

  async created() {
    // 获取模板的详情信息
    let {params} = (this.$route);
    if (params?.type === "detail") {
      await this.getTemplateInfo();
    } else {
      let temp = localStorage.getItem('templateInfo')
      await this.$store.dispatch('templateDetails/setTemplateDataInfo', JSON.parse(temp))
    }
  },

  mounted() {
    const self = this;
    self.isProd = (process.env.NODE_ENV) === 'development';
    self.$store.dispatch('setReportStepInfo', 0)
    /* 禁用Firefox默认拖拽搜索功能!! */
    self.disableFirefoxDefaultDrop();
    self.designer.registerFormWidget(self);
    window.addEventListener('resize', lodash.throttle(() => {
      self.changeCanvas()
    }, 2000))
  },

  methods: {
    getScaleSize(width = 1920, height = 1080) {
      const self = this;
      /*
       用视口当前的宽高除以设计图宽高，如果小于1表示屏幕缩小了，反之屏幕放大了，那scale也就应该进行对应的放大或缩小，并且缩放时宽高应该是等比例缩放。
       如果 ww = wh 表示屏幕是在根据设计图宽高等比例缩放。
       如果 ww < wh 表示在等比缩放基础上宽度更小，为了让所有内容都能居中显示在屏幕中，就需要scale按照ww这个比例来缩放宽高。
       如果 ww > wh 表示在等比缩放基础上高度更小，为了让所有内容都能居中显示在屏幕中，就需要scale按照wh这个比例来缩放宽高。
       口诀：基于设计图宽高比，实时视口 宽更小就使用 视口宽/设计图宽 的比值来等比缩放。高更小就使用 视口高/设计图高 的比值来等比缩放
   */
      let targetX = 1920;
      let targetY = 1080;
      let targetRatio = 16 / 9;
      let sideX = 0;
      let sideY = 0;
      let currentX = self.$refs?.preViewRef?.offsetWidth || 1920;
      let currentY = self.$refs?.preViewRef?.offsetHeight || 1080;
      // number > 100 && number < 200 currentX >= 1320
      if (currentX >= 1320 && currentX < 1920) {
        sideX = 620
        sideY = 60
      } else if(currentX >= 1922) {
        sideX = 1220
        sideY = 600
      }else {
        sideX = 80
        sideY = 60
      }
      let offsetWidth = currentX - sideX;
      let offsetHeight = currentY - sideY;
      const ww = parseInt(offsetWidth) / parseInt(width);
      const wh = parseInt(offsetHeight) / parseInt(height);
      return ww < wh ? ww : wh
    },

    changeCanvas() {
      const self = this;
      let [initW, initH] = self.deviceSize.split('*');
      if ((self.$refs.cvsRef)) {
        self.$nextTick(() => {
          let scale = self.getScaleSize(initW, initH);
          self.$refs.cvsRef.style.transform = `scale(${Math.abs(scale)}) translate(-50%, -50%)`;
          self.$refs.cvsRef.style.width = `${pxToVw(parseInt(initW))}`;
          self.$refs.cvsRef.style.height = `${pxToVw(parseInt(initH))}`;
        })
      }
    },

    getWidgetName(widget) {
      // console.log(`${widget.type}-widget`)
      return `${widget.type}-widget`;
    },

    getWidgetShow(widget) {
      if (widget.type === 'scene-tips') {
        let info = this.$store.getters['getReportStepInfo'];
        return info !== 1
      } else {
        return true
      }
    },

    disableFirefoxDefaultDrop() {
      let isFirefox = (navigator.userAgent.toLowerCase().indexOf("firefox") !== -1);
      if (isFirefox) {
        document.body.ondrop = function (event) {
          event.stopPropagation();
          event.preventDefault();
        };
      }
    },

    onDragEnd(evt) {
      //console.log('拖拽结束', evt)
    },

    onDragAdd(evt) {
      const newIndex = evt.newIndex;
      if (!!this.designer.widgetList[newIndex]) {
        this.designer.setSelected(this.designer.widgetList[newIndex]);
      }
      this.designer.emitHistoryChange();
      this.designer.emitEvent("field-selected", null);
    },

    onDragUpdate() {
      this.designer.emitHistoryChange();
    },

    checkMove(evt) {
      return this.designer.checkWidgetMove(evt);
    },

    getFormData() {
      return this.formModel;
    },

    getWidgetRef(widgetName, showError = false) {
      let foundRef = this.widgetRefList[widgetName];
      if (!foundRef && !!showError) {
        this.$message.error("render.hint.refNotFound" + widgetName);
      }
      return foundRef;
    },

    getSelectedWidgetRef() {
      let wName = this.designer.selectedWidgetName;
      return this.getWidgetRef(wName);
    },

    // 清除视图的组件
    clearFormWidget() {
      this.designer.clearDesigner();
      this.designer.formWidget.clearWidgetRefList()
    },

    // 可跨组件清除
    clearWidgetRefList() {
      Object.keys(this.widgetRefList).forEach(key => {
        delete this.widgetRefList[key]
      })
    },

    // 删除对应的组件
    deleteWidgetRef(widgetRefName, fieldWidgetInfo) {
      this.$emit('handleDeleteWidget', (fieldWidgetInfo.type))
      delete this.widgetRefList[widgetRefName];
    },

    // 预览视图
    handlePreview() {
      console.log('预览视图')
    },

    // 上屏预览
    async handleUpScreenPreview() {
      let widgetList = deepClone(this.designer.widgetList);
      let formConfig = deepClone(this.designer.formConfig);
      let templateInfo = localStorage.getItem('templateInfo');
      let tempInfo = JSON.parse(templateInfo);
      // 发起上屏预览申请
      await ApiUtils.upScreenPreview(this, formConfig, widgetList, tempInfo.resolution);
    },
    // 发布模板
    async handlePublic() {
      const self = this;
      let info = self.$store.getters['getReportStepInfo'];
      let widgetList = deepClone(self.designer.widgetList);
      let formConfig = deepClone(self.designer.formConfig);
      if (info === 1) {
        (widgetList).map(fileName => {
          let compType = fileName?.type;
          if (compType === 'scene-report-info' || compType === 'scene-report-auto-info') {
            let config = fileName?.options?.config;
            let options = fileName.options[config]
            Reflect.set(options, 'step', 0)
            self.$store.dispatch('setReportStepInfo', 0);
          }
        })
      }
      if (widgetList?.length) {
        let paramsInfo = Object();
        let {params} = (self.$route);
        let templateInfo = localStorage.getItem('templateInfo');
        let tempInfo = JSON.parse(templateInfo);
        if ((params.type) === 'create') {
          Reflect.set(tempInfo, 'widgetList', JSON.stringify(widgetList))
          Reflect.set(tempInfo, 'formConfig', JSON.stringify(formConfig))
          paramsInfo = {...tempInfo}
        } else if ((params.type) === 'detail') {
          let templateInfo = deepClone(self.templateInfo);
          Reflect.set(templateInfo, 'formConfig', JSON.stringify(formConfig));
          Reflect.set(templateInfo, 'widgetList', JSON.stringify(widgetList))
          paramsInfo = {...templateInfo}
        }
        console.log(templateInfo)
        let {code, data} = await ModelDesignApi.createHtml(paramsInfo);
        if (code === 200) {
          let [initW, initH] = self.deviceSize.split('*');
          // 组件信息
          Reflect.set((self.previewInfo), 'visible', true);
          Reflect.set((self.previewInfo), 'id', (data.id));
          Reflect.set((self.previewInfo), 'htmlPath', (data.htmlPath));
          Reflect.set((self.previewInfo), 'resolution', {width: initW, height: initH});
        } else {
          self.$message({
            message: '组件发布失败,请检查后再操作.',
            type: 'warning',
          });
        }
      } else {
        self.$message({
          message: '请在画布中拖入组件在发布.',
          type: 'warning'
        });
      }
    },

    //组件导出-弹层
    handleExport() {
      let widgetList = deepClone(this.designer.widgetList);
      let formConfig = deepClone(this.designer.formConfig);
      let jsonContent = JSON.stringify({widgetList, formConfig}, null, '  ');
      Reflect.set((this.exportInfo), 'visible', true);
      Reflect.set((this.exportInfo), 'jsonContent', jsonContent);
    },

    // 返回列表页
    handleBack() {
      this.$router.push({
        path: '/template'
      });
    },

    // 关闭弹层
    handleCancel() {
      Reflect.set((this.exportInfo), 'visible', false);
      Reflect.set((this.previewInfo), 'visible', false);
      this.$store.dispatch('setReportStepInfo', 0);
      this.uuid = uuid();
    },

    // 获取模板的详情信息--可能存在取不到数据的情况
    async getTemplateInfo() {
      let {params} = (this.$route);
      let param = Object();
      Reflect.set(param, 'id', (params.id));
      // 获取模板的详情
      await this.$store.dispatch('templateDetails/setTemplateInfo', param);
    }
  },

  // 销毁模板缓存数据
  beforeDestroy() {
    localStorage.removeItem('widget__list__backup');
    localStorage.removeItem('form__config__backup');
  },

  watch: {
    "designer.widgetList": {
      handler(val) {
        // console.log(val)
      },
      deep: true,
    },

    "designer.formConfig": {
      handler(val) {
        // console.log(val)
      },
      deep: true,
    },

    "designer.selectedWidget": {
      handler(val) {
        // console.log(val)
      },
      deep: true,
    },


    templateInfo: {
      handler(val) {
        this.deviceSize = (val.resolution) || '1920*1080';
        this.designer.initDesigner(!!this.getDesignerConfig().resetFormJson);
        this.designer.loadPresetCssCode(this.getDesignerConfig().presetCssCode);
        setTimeout(() => {
          this.changeCanvas();
        }, 500)

      },
      deep: true,
      immediate: true
    }
  },
};
</script>

<style lang="scss" scoped>
@import "./assets/style";
</style>
